package com.yunti.springboot.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunti.springboot.bo.UserBO;
import com.yunti.springboot.commonenum.SubjectEnum;
import com.yunti.springboot.config.component.AbstractCurrentRequestComponent;
import com.yunti.springboot.mapper.*;
import com.yunti.springboot.po.*;
import com.yunti.springboot.po.Class;
import com.yunti.springboot.service.ScoreRuleService;
import com.yunti.springboot.service.ScoreService;
import com.yunti.springboot.util.GradeYearUtil;
//import com.yunti.springboot.util.ScoreExcelUtils;
import com.yunti.springboot.util.NumUtils;
import com.yunti.springboot.util.ScoreWordUtil;
import com.yunti.springboot.vo.Result;
import com.yunti.springboot.vo.req.ClassOverViewReq;
import com.yunti.springboot.vo.req.ScoreCollectReq;
import com.yunti.springboot.vo.req.ScoreTableReq;
import com.yunti.springboot.vo.req.UpdateScoreReq;
import com.yunti.springboot.vo.res.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service
public class ScoreServiceImpl extends ServiceImpl<ScoreMapper, Score> implements ScoreService {

    @Resource
    private StudentMapper studentMapper;

    @Resource
    private ScoreRuleService scoreRuleService;

    @Resource
    private SubItemMapper subItemMapper;

    @Resource
    private OptionMapper optionMapper;

    @Resource
    private ElectiveSubMapper electiveSubMapper;
    @Resource
    private ClassMapper classMapper;
    @Resource
    private AbstractCurrentRequestComponent abstractCurrentRequestComponent;
    @Resource
    private ScoreMapper scoreMapper;

    @Resource
    private SubjectMapper subjectMapper;
    @Resource
    private SchoolMapper schoolMapper;
    @Override
    public Result updateScore(UpdateScoreReq updateScoreReq) {
        Score score = new Score();
        score.setRawScore(updateScoreReq.getScore());
        score.setCount(updateScoreReq.getCount());
        score.setCreateTime(LocalDateTime.now());
        score.setItemNo(updateScoreReq.getItemNo());
        score.setStuId(updateScoreReq.getStuId());
        score.setElectiveId(updateScoreReq.getElectiveId());

        Student student = studentMapper.selectById(updateScoreReq.getStuId());

        ElectiveSub electiveSub = electiveSubMapper.selectById(updateScoreReq.getElectiveId());


        SubItem subItem = null;
        if(electiveSub.getSubId()!=-1){
            LambdaQueryWrapper<SubItem> subItemLambdaQueryWrapper = new LambdaQueryWrapper<>();
            subItemLambdaQueryWrapper.eq(SubItem::getSubId,electiveSub.getSubId());
            subItemLambdaQueryWrapper.eq(SubItem::getItemNo,updateScoreReq.getItemNo());
            subItemLambdaQueryWrapper.and(l -> l.eq(SubItem::getSextype,0).or().eq(SubItem::getSextype,student.getSex()));
            subItem = subItemMapper.selectOne(subItemLambdaQueryWrapper);
        }else{
            LambdaQueryWrapper<Option> optionLambdaQueryWrapper = new LambdaQueryWrapper<>();
            optionLambdaQueryWrapper.eq(Option::getElectiveSubId,updateScoreReq.getElectiveId());
            optionLambdaQueryWrapper.eq(Option::getStuId,updateScoreReq.getStuId());
            Option option = optionMapper.selectOne(optionLambdaQueryWrapper);

            LambdaQueryWrapper<SubItem> subItemLambdaQueryWrapper = new LambdaQueryWrapper<>();
            subItemLambdaQueryWrapper.eq(SubItem::getSubId,option.getSubId());
            subItemLambdaQueryWrapper.eq(SubItem::getItemNo,updateScoreReq.getItemNo());
            subItemLambdaQueryWrapper.and(l -> l.eq(SubItem::getSextype,0).or().eq(SubItem::getSextype,student.getSex()));
            subItem = subItemMapper.selectOne(subItemLambdaQueryWrapper);
        }

        assert subItem != null;
        score.setSubId(subItem.getSubId());
        ScoreRule scoreRule = (ScoreRule) scoreRuleService.getScoreByRawScore(student.getSex(),subItem.getId(),updateScoreReq.getScore()).getData();
        if(scoreRule != null){
            score.setConversionScore(scoreRule.getConvScore());
        }

        LambdaQueryWrapper<Score> scoreLambdaQueryWrapper = new LambdaQueryWrapper<>();
        scoreLambdaQueryWrapper.eq(Score::getCount, updateScoreReq.getCount());
        scoreLambdaQueryWrapper.eq(Score::getItemNo, updateScoreReq.getItemNo());
        scoreLambdaQueryWrapper.eq(Score::getStuId,updateScoreReq.getStuId());
        scoreLambdaQueryWrapper.eq(Score::getElectiveId, updateScoreReq.getElectiveId());

        if(baseMapper.exists(scoreLambdaQueryWrapper)){
            update(score,scoreLambdaQueryWrapper);
        }else{
            save(score);
        }
        return null;
    }

    @Override
    public void downloadScore(ScoreTableReq scoreTableReq, HttpServletResponse response) {
        UserBO userBO = abstractCurrentRequestComponent.getCurrentStaffId();
        Integer school_id = userBO.getSchoolId();
        LambdaQueryWrapper<Student> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Student::getSchoolId,school_id);
        lambdaQueryWrapper.eq(Objects.nonNull(scoreTableReq.getYear()),Student::getYear, GradeYearUtil.getGradeYearByYear(scoreTableReq.getYear()));
        lambdaQueryWrapper.orderByAsc(Student::getClassId);
        lambdaQueryWrapper.orderByAsc(Student::getId);
        List<Student>students  =  studentMapper.selectList(lambdaQueryWrapper);
        if(students.size()==0){
               return;
        }
        //获取选科
        LambdaQueryWrapper<ElectiveSub> queryWrapper = new LambdaQueryWrapper<>();
        if(scoreTableReq.getYear()!=null){
            if(scoreTableReq.getYear() == 1){
                List<Integer> semesterList = new ArrayList<>();
                semesterList.add(1);
                semesterList.add(2);
                queryWrapper.in(ElectiveSub::getSemester,semesterList);
            }
            if(scoreTableReq.getYear() == 2){
                List<Integer> semesterList = new ArrayList<>();
                semesterList.add(3);
                semesterList.add(4);
                queryWrapper.in(ElectiveSub::getSemester,semesterList);
            }
            if(scoreTableReq.getYear() == 3){
                List<Integer> semesterList = new ArrayList<>();
                semesterList.add(5);
                semesterList.add(6);
                queryWrapper.in(ElectiveSub::getSemester,semesterList);
            }
        }
        //某个年级选课（选修，必修）
        List<ElectiveSub>list = electiveSubMapper.selectList(queryWrapper);
        //选修
        List<ElectiveSub> optionElectiveList = list.stream().filter(a -> a.getSubId() == -1).collect(Collectors.toList());
        //查询每个考生的选修
        for (Student student : students) {
        for (ElectiveSub sub : optionElectiveList) {
            LambdaQueryWrapper<Option>lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
            lambdaQueryWrapper1.eq(Option::getStuId,student.getId());
            lambdaQueryWrapper1.eq(Option::getElectiveSubId,sub.getId());
            List<Option>optionList = optionMapper.selectList(lambdaQueryWrapper1);
            if(optionList.size()== 0){
                //未选
                Option option = new Option();
                option.setSubId(-1);
                List<Option>options =student.getOptions();
                options.add(option);
                student.setOptions(options);
            }else {
                //已选
                Option option = optionList.get(0);
                List<Option>options =student.getOptions();
                options.add(option);
                student.setOptions(options);
            }
        }
        }
        //查询某个年级所有的分数
        LambdaQueryWrapper<Score> scoreLambdaQueryWrapper = new LambdaQueryWrapper<>();
        scoreLambdaQueryWrapper.in(Score::getElectiveId);
        List<Score> scoreList = scoreMapper.selectList(scoreLambdaQueryWrapper);

//        if(scoreTableReq.getYear() == 1){
//            ScoreExcelUtils.outputSevenScore(students,list,scoreList,response);
//        }
//        if(scoreTableReq.getYear() == 2){
//            ScoreExcelUtils.outputEightScore(students,list,scoreList,response);
//        }
//        if(scoreTableReq.getYear() == 3){
//            ScoreExcelUtils.outputScore(students,list,scoreList,response);
//        }
    }

    @Override
    public Result getClassOverView(ClassOverViewReq classOverViewReq) {
        ClassOverViewRes classOverViewRes = new ClassOverViewRes();
        UserBO userBO = abstractCurrentRequestComponent.getCurrentStaffId();
        Integer school_id = userBO.getSchoolId();
        Class aClass = classMapper.selectById(classOverViewReq.getClassId());
        classOverViewRes.setClassMsg(aClass);
        if(aClass == null){
            return Result.error("班级不存在");
        }
        int totalScore = 0;
        //通过班级，入学学年，对应学校查询学生
        LambdaQueryWrapper<Student> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Student::getSchoolId,school_id);
        lambdaQueryWrapper.eq(Objects.nonNull(classOverViewReq.getYear()),Student::getYear, GradeYearUtil.getGradeYearByYear(classOverViewReq.getYear()));
        lambdaQueryWrapper.eq(Objects.nonNull(classOverViewReq.getClassId()),Student::getClassId, classOverViewReq.getClassId());
        lambdaQueryWrapper.orderByAsc(Student::getId);
        List<Student>students  =  studentMapper.selectList(lambdaQueryWrapper);
        if(students.size()==0){
            return Result.error("考生个数为零","考生个数为零");
        }
        List<Integer> stuIdList = students.stream().map(Student::getId).collect(Collectors.toList());
        Map<Integer,Student> studentMap = students.stream().collect(Collectors.toMap(Student::getId, Function.identity()));


        //获取选科。某个学年选科（选修，必修）
        LambdaQueryWrapper<ElectiveSub> queryWrapper = new LambdaQueryWrapper<>();
        if(classOverViewReq.getSchoolYear()!=null){
            if(classOverViewReq.getSchoolYear() == 1){
                List<Integer> semesterList = new ArrayList<>();
                semesterList.add(1);
                semesterList.add(2);
                queryWrapper.in(ElectiveSub::getSemester,semesterList);
                totalScore = 20;
            }
            if(classOverViewReq.getSchoolYear() == 2){
                List<Integer> semesterList = new ArrayList<>();
                semesterList.add(3);
                semesterList.add(4);
                queryWrapper.in(ElectiveSub::getSemester,semesterList);
                totalScore = 40;
            }
            if(classOverViewReq.getSchoolYear() == 3){
                List<Integer> semesterList = new ArrayList<>();
                semesterList.add(5);
                semesterList.add(6);
                queryWrapper.in(ElectiveSub::getSemester,semesterList);
                totalScore = 40;
            }
        }
        List<ElectiveSub>list = electiveSubMapper.selectList(queryWrapper);
        List<Integer> electiveIdList = list.stream().map(ElectiveSub::getId).collect(Collectors.toList());

        //查询某个班级某个学年的所有成绩
        LambdaQueryWrapper<Score> scoreLambdaQueryWrapper = new LambdaQueryWrapper<>();
        scoreLambdaQueryWrapper.in(Score::getElectiveId,electiveIdList);
        scoreLambdaQueryWrapper.in(Score::getStuId,stuIdList);
        List<Score> scoreList = scoreMapper.selectList(scoreLambdaQueryWrapper);
        //按学生分组
        Map<Integer,List<Score>> scoreMap = scoreList.stream().collect(Collectors.groupingBy(Score::getStuId));

        //统计班级男生、女生个数
        classOverViewRes.setNumOfBoy((int) students.stream().filter(e -> e.getSex() == 1).count());
        classOverViewRes.setNumOfGirl((int) students.stream().filter(e -> e.getSex() == 2).count());

        Map<Integer, List<Double>> subScoreListMap = new HashMap<>();
        for (ElectiveSub sub: list) {
            subScoreListMap.put(sub.getSubId(),new ArrayList<>());
        }

        int numOfBoyTest = 0;
        int numOfGirlTest = 0;

        int numOfYxScore = 0;
        int numOfLhScore = 0;
        int numOfHgScore = 0;
        int numOfBhgScore = 0;

        int numOfBoyYxScore = 0;
        int numOfBoyLhScore = 0;
        int numOfBoyHgScore = 0;
        int numOfBoyBhgScore = 0;

        double totalStuScore = 0;

        HashMap<Integer,Double> scoreBoysMap = new HashMap<>();
        HashMap<Integer,Double> scoreGirlsMap = new HashMap<>();

        for (Student student: students) {
            List<Score> stuScoreList =  scoreMap.get(student.getId());
            if (stuScoreList == null){
                continue;
            }
            List<TransScoreRes> transScoreList = new ArrayList<>();
            boolean isTest = false;
            for (ElectiveSub sub:  list) {
                //每一科的成绩
                List<Score> scores = stuScoreList.stream().filter(a -> Objects.equals(a.getSubId() , sub.getSubId())).collect(Collectors.toList());
                if (scores.isEmpty()) continue;
                TransScoreRes transScore = getScore(sub,scores);
                transScoreList.add(transScore);
                subScoreListMap.get(sub.getSubId()).add(Double.parseDouble(transScore.getConvScore()));
                isTest = true;
            }
            //如果没测试过就不进行算分数
            if(!isTest)continue;

            double sum_score=0.00;
            for (TransScoreRes transScore : transScoreList) {
                sum_score+=Double.parseDouble(transScore.getConvScore());
            }

            if(student.getSex() == 1){
                scoreBoysMap.put(student.getId(),sum_score);
            }

            if(student.getSex() == 2){
                scoreGirlsMap.put(student.getId(),sum_score);
            }

            if(isTest && student.getSex() == 1){
                numOfBoyTest++;
            }

            if(isTest && student.getSex() == 2){
                numOfGirlTest++;
            }

            if(sum_score >= totalScore * 0.8){
                numOfYxScore++;
                if(student.getSex() == 1){
                    numOfBoyYxScore++;
                }
            }
            else if(sum_score >= totalScore * 0.7){
                numOfLhScore++;
                if(student.getSex() == 1){
                    numOfBoyLhScore++;
                }
            }
            else if(sum_score >= totalScore * 0.6){
                numOfHgScore++;
                if(student.getSex() == 1){
                    numOfBoyHgScore++;
                }
            }
            else{
                numOfBhgScore++;
                if(student.getSex() == 1){
                    numOfBoyBhgScore++;
                }
            }

            totalStuScore += sum_score;
        }



        List<Integer> boyStuId = scoreBoysMap.entrySet().stream().sorted( Map.Entry.<Integer,Double>comparingByValue().reversed()).map(Map.Entry::getKey).collect(Collectors.toList());
        List<Integer> girlStuId = scoreGirlsMap.entrySet().stream().sorted(Map.Entry.<Integer,Double>comparingByValue().reversed()).map(Map.Entry::getKey).collect(Collectors.toList());

        if(boyStuId.size() >= 1){
            classOverViewRes.setFirstBoyStudent(studentMap.get(boyStuId.get(0)));
            classOverViewRes.setFirstBoyStudentScore(NumUtils.saveTwoPoint(scoreBoysMap.get(boyStuId.get(0))));
        }
        if(girlStuId.size() >= 1){
            classOverViewRes.setFirstGirlStudent(studentMap.get(girlStuId.get(0)));
            classOverViewRes.setFirstGirlStudentScore(NumUtils.saveTwoPoint(scoreGirlsMap.get(girlStuId.get(0))));
        }

        if(boyStuId.size() >= 2){
            classOverViewRes.setSecondBoyStudent(studentMap.get(boyStuId.get(1)));
            classOverViewRes.setSecondBoyStudentScore(NumUtils.saveTwoPoint(scoreBoysMap.get(boyStuId.get(1))));
        }
        if(girlStuId.size() >= 2){
            classOverViewRes.setSecondGirlStudent(studentMap.get(girlStuId.get(1)));
            classOverViewRes.setSecondGirlStudentScore(NumUtils.saveTwoPoint(scoreGirlsMap.get(girlStuId.get(1))));
        }

        if(boyStuId.size() >= 3){
            classOverViewRes.setThirdBoyStudent(studentMap.get(boyStuId.get(2)));
            classOverViewRes.setThirdBoyStudentScore(NumUtils.saveTwoPoint((scoreBoysMap.get(boyStuId.get(2)))));
        }
        if(girlStuId.size() >= 3){
            classOverViewRes.setThirdGirlStudent(studentMap.get(girlStuId.get(2)));
            classOverViewRes.setThirdGirlStudentScore(NumUtils.saveTwoPoint((scoreGirlsMap.get(girlStuId.get(2)))));
        }

        List<ClassOverViewRes.subScore> subScoreList = new ArrayList<>();


        Set<Integer> keyset = subScoreListMap.keySet();
        for(Integer key:keyset){
            if(key ==0)continue;
            ClassOverViewRes.subScore subScore = new ClassOverViewRes.subScore();
            List<Double> subItemScoreList = subScoreListMap.get(key);
            if(subItemScoreList == null || subItemScoreList.size() ==0)continue;
            subScore.setMaxScore(NumUtils.saveTwoPoint(Collections.max(subItemScoreList)));
            subScore.setMinScore(NumUtils.saveTwoPoint(Collections.min(subItemScoreList)));
            subScore.setAvgScore(NumUtils.saveTwoPoint(NumUtils.getAvg(subItemScoreList)));
            subScore.setSubId(key);
            subScore.setSubName(SubjectEnum.getNameById(key));
            subScoreList.add(subScore);
        }

        classOverViewRes.setSubScoreList(subScoreList);

        classOverViewRes.setNumOfBoyTest(numOfBoyTest);
        classOverViewRes.setNumOfGirlTest(numOfGirlTest);
        classOverViewRes.setNumOfYxScore(numOfYxScore);
        classOverViewRes.setNumOfLhScore(numOfLhScore);
        classOverViewRes.setNumOfHgScore(numOfHgScore);
        classOverViewRes.setNumOfBhgScore(numOfBhgScore);
        classOverViewRes.setClassAvgScore(NumUtils.saveTwoPoint(totalStuScore/students.size()));

        classOverViewRes.setNumOfBoyYxScore(numOfBoyYxScore);
        classOverViewRes.setNumOfBoyLhScore(numOfBoyLhScore);
        classOverViewRes.setNumOfBoyHgScore(numOfBoyHgScore);
        classOverViewRes.setNumOfBoyBhgScore(numOfBoyBhgScore);

        return Result.success(classOverViewRes);

    }

    @Override
    public Result getScoreCollect(ScoreCollectReq req) {
        if (req.getCurrent() == null) {
            req.setCurrent(1);
        }
        if (req.getSize() == null) {
            req.setSize(10);
        }
        Page page = new Page<>(req.getCurrent(), req.getSize());
        LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
        UserBO userBO = abstractCurrentRequestComponent.getCurrentStaffId();
        queryWrapper.eq(Student::getSchoolId, userBO.getSchoolId());
        queryWrapper.eq(Objects.nonNull(req.getId()),Student::getId, req.getId());
        queryWrapper.like(StrUtil.isNotBlank(req.getStuName()) ,Student::getName, req.getStuName());
        queryWrapper.eq(StrUtil.isNotBlank(req.getStuNo()),Student::getStuNo, req.getStuNo());
        queryWrapper.eq(StrUtil.isNotBlank(req.getClassId()),Student::getClassId, req.getClassId());
        queryWrapper.eq(Objects.nonNull(req.getSex()),Student::getSex, req.getSex());
        if (Objects.nonNull(req.getYear())){
            queryWrapper.eq(Objects.nonNull(req.getYear()),Student::getYear, GradeYearUtil.getGradeYearByYear(req.getYear()));
        }else {
            queryWrapper.eq(Student::getYear,GradeYearUtil.getGradeYear());
        }

        Page students = studentMapper.selectPage(page, queryWrapper);
        List<Student> records = students.getRecords();

        //获取每学期的考试科目
        LambdaQueryWrapper<ElectiveSub> subLambdaQueryWrapper = new LambdaQueryWrapper<>();
        subLambdaQueryWrapper.eq(Objects.nonNull(req.getSemester()),ElectiveSub::getSemester,req.getSemester());
//        subLambdaQueryWrapper.eq(Objects.nonNull(req.getYear()),ElectiveSub::getYear,req.getYear());
        List<ElectiveSub>electiveSubList = electiveSubMapper.selectList(subLambdaQueryWrapper);

        List<ScoreCollectRes> scoreCollectResList = new LinkedList<>();
        for (Student student : records) {
            //查询班级
            Class aClass = classMapper.selectById(student.getClassId());
            if(aClass != null){
                student.setClassName(aClass.getClassName());
            }
            ScoreCollectRes res = new ScoreCollectRes();
            res.setStuId(student.getId());
            res.setSex(student.getSex());
            res.setStuName(student.getName());
            res.setStuNo(student.getStuNo());
            res.setClassId(student.getClassId());
            res.setClassName(student.getClassName());
            res.setYear(student.getYear());
            //获取选科科目
            LambdaQueryWrapper<Option> optionLambdaQueryWrapper = new LambdaQueryWrapper<>();
            optionLambdaQueryWrapper.eq(Option::getStuId, student.getId());
            List<Option> optionList = optionMapper.selectList(optionLambdaQueryWrapper);
            Map<Integer, Option> optionMap = optionList.stream().collect(Collectors.toMap(Option::getElectiveSubId, Function.identity(), (k1, k2) -> k1));
            List<Integer> selectSubList = optionList.stream().map(Option::getSubId).distinct().collect(Collectors.toList());

            //通过科目id获取详情
            List<Integer> subIdList = electiveSubList.stream().map(ElectiveSub::getSubId).collect(Collectors.toList());
            subIdList.addAll(selectSubList);
            LambdaQueryWrapper<Subject> subjectLambdaQueryWrapper = new LambdaQueryWrapper<>();
            subjectLambdaQueryWrapper.in(Subject::getId, subIdList);
            List<Subject> subjectList = subjectMapper.selectList(subjectLambdaQueryWrapper);
            Map<Integer, Subject> subjectMap = subjectList.stream().collect(Collectors.toMap(Subject::getId, Function.identity(), (k1, k2) -> k1));

            //通过科目id获取子项目
            LambdaQueryWrapper<SubItem> subItemLambdaQueryWrapper = new LambdaQueryWrapper<>();
            subItemLambdaQueryWrapper.in(SubItem::getSubId, subIdList);
            List<SubItem> subItemList = subItemMapper.selectList(subItemLambdaQueryWrapper);
            Map<Integer, List<SubItem>> subItemListMap = subItemList.stream().collect(Collectors.groupingBy(SubItem::getSubId));

            //获取分数
            List<Integer> electiveSubIdList = electiveSubList.stream().map(ElectiveSub::getId).distinct().collect(Collectors.toList());
            LambdaQueryWrapper<Score> scoreLambdaQueryWrapper = new LambdaQueryWrapper<Score>();
            scoreLambdaQueryWrapper.eq(Score::getStuId, student.getId());
            scoreLambdaQueryWrapper.in(Score::getElectiveId, electiveSubIdList);
            List<Score> scoreList = scoreMapper.selectList(scoreLambdaQueryWrapper);
            List<ScoreCollectRes.Sub> subList = new LinkedList();
            for (ElectiveSub electiveSub: electiveSubList) {
                ScoreCollectRes.Sub sub = new ScoreCollectRes.Sub();
                sub.setSubId(electiveSub.getSubId());
                sub.setElectiveId(electiveSub.getId());
                sub.setYear(electiveSub.getYear());
                sub.setSemester(electiveSub.getSemester());
                sub.setType(electiveSub.getType());
                if (sub.getSubId() == -1) {
                    if (optionMap.get(electiveSub.getId()) != null) {
                        sub.setSubId(optionMap.get(electiveSub.getId()).getSubId());
                    }
                }
                if (sub.getSubId() != -1 && subjectMap.get(sub.getSubId()) != null) {
                    //设置科目名
                    sub.setSubName(subjectMap.get(sub.getSubId()).getName());
                    //获取子项目,并过滤性别
                    List<SubItem> childSubItemList = subItemListMap.get(sub.getSubId()).stream().filter(e -> !e.getItemNo().equals(0) && (e.getSextype().equals(0) || e.getSextype().equals(student.getSex()))).collect(Collectors.toList());
                    List<ScoreCollectRes.Item> items = new ArrayList<>();
                    for (SubItem subItem: childSubItemList) {
                        ScoreCollectRes.Item item = new ScoreCollectRes.Item();
                        item.setItemNo(subItem.getItemNo());
                        item.setUnit(subItem.getUnit());
                        item.setItemName(subItem.getName());
                        List<Score> childScoreList = scoreList.stream().filter(new Predicate<Score>() {
                            @Override
                            public boolean test(Score score) {
                                return !score.getItemNo().equals(0) && score.getItemNo().equals(subItem.getItemNo()) && score.getElectiveId().equals(electiveSub.getId());
                            }
                        }).collect(Collectors.toList());

                        item.setScoreList(childScoreList);
                        items.add(item);
                    }
                    sub.setItems(items);
                    //获取大项,并过滤性别
                    List<SubItem> subItems = subItemListMap.get(sub.getSubId()).stream().filter(e -> e.getItemNo().equals(0) && (e.getSextype().equals(0) || e.getSextype().equals(student.getSex()))).collect(Collectors.toList());
                    if (scoreList.size() > 0) {
                        SubItem subItem = subItems.get(0);
                        sub.setSubName(subItem.getName());
                        sub.setUnit(subItem.getUnit());
                    }

                    sub.setScoreList(scoreList.stream().filter(new Predicate<Score>() {
                        @Override
                        public boolean test(Score score) {
                            return score.getItemNo().equals(0) && score.getElectiveId().equals(electiveSub.getId());
                        }
                    }).collect(Collectors.toList()));
                }
                subList.add(sub);
            }
            res.setSubs(subList);
            scoreCollectResList.add(res);
        }
        students.setRecords(scoreCollectResList);
        return Result.success(students);
    }

    @Override
    public Result downScoreCollect(ScoreCollectReq req, HttpServletResponse response) {
        LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
        UserBO userBO = abstractCurrentRequestComponent.getCurrentStaffId();
        queryWrapper.eq(Student::getSchoolId, userBO.getSchoolId());
        queryWrapper.eq(Objects.nonNull(req.getId()),Student::getId, req.getId());
        queryWrapper.like(StrUtil.isNotBlank(req.getStuName()) ,Student::getName, req.getStuName());
        queryWrapper.eq(StrUtil.isNotBlank(req.getStuNo()),Student::getStuNo, req.getStuNo());
        queryWrapper.eq(StrUtil.isNotBlank(req.getClassId()),Student::getClassId, req.getClassId());
        queryWrapper.eq(Objects.nonNull(req.getSex()),Student::getSex, req.getSex());
        if (Objects.nonNull(req.getYear())){
            queryWrapper.eq(Objects.nonNull(req.getYear()),Student::getYear, GradeYearUtil.getGradeYearByYear(req.getYear()));
        }else {
            queryWrapper.eq(Student::getYear,GradeYearUtil.getGradeYear());
        }
        List<Student> studentList = studentMapper.selectList(queryWrapper);

        //获取每学期的考试科目
        LambdaQueryWrapper<ElectiveSub> subLambdaQueryWrapper = new LambdaQueryWrapper<>();
        subLambdaQueryWrapper.eq(Objects.nonNull(req.getSemester()),ElectiveSub::getSemester,req.getSemester());
//        subLambdaQueryWrapper.eq(Objects.nonNull(req.getYear()),ElectiveSub::getYear,req.getYear());
        List<ElectiveSub>electiveSubList = electiveSubMapper.selectList(subLambdaQueryWrapper);

        List<StudentVo> studentRes = new ArrayList<>();
        for (Student student : studentList) {
            BigDecimal total = new BigDecimal(0);
            //查询班级
            Class aClass = classMapper.selectById(student.getClassId());
            if(aClass != null){
                student.setClassName(aClass.getClassName());
            }
            StudentVo res = new StudentVo()
                    .setId(student.getId())
                    .setClassId(student.getClassId())
                    .setClassName(student.getClassName())
                    .setStuNo(student.getStuNo())
                    .setName(student.getName())
                    .setSex(student.getSex()!=null&&student.getSex()==1?"男":"女");
            //获取选科科目
            LambdaQueryWrapper<Option> optionLambdaQueryWrapper = new LambdaQueryWrapper<>();
            optionLambdaQueryWrapper.eq(Option::getStuId, student.getId());
            List<Option> optionList = optionMapper.selectList(optionLambdaQueryWrapper);
            Map<Integer, Option> optionMap = optionList.stream().collect(Collectors.toMap(Option::getElectiveSubId, Function.identity(), (k1, k2) -> k1));
            List<Integer> selectSubList = optionList.stream().map(Option::getSubId).distinct().collect(Collectors.toList());

            //通过科目id获取详情
            List<Integer> subIdList = electiveSubList.stream().map(ElectiveSub::getSubId).collect(Collectors.toList());
            subIdList.addAll(selectSubList);
            LambdaQueryWrapper<Subject> subjectLambdaQueryWrapper = new LambdaQueryWrapper<>();
            subjectLambdaQueryWrapper.in(Subject::getId, subIdList);
            List<Subject> subjectList = subjectMapper.selectList(subjectLambdaQueryWrapper);
            Map<Integer, Subject> subjectMap = subjectList.stream().collect(Collectors.toMap(Subject::getId, Function.identity(), (k1, k2) -> k1));

            //通过科目id获取子项目
            LambdaQueryWrapper<SubItem> subItemLambdaQueryWrapper = new LambdaQueryWrapper<>();
            subItemLambdaQueryWrapper.in(SubItem::getSubId, subIdList);
            List<SubItem> subItemList = subItemMapper.selectList(subItemLambdaQueryWrapper);
            Map<Integer, List<SubItem>> subItemListMap = subItemList.stream().collect(Collectors.groupingBy(SubItem::getSubId));

            //获取分数
            List<Integer> electiveSubIdList = electiveSubList.stream().map(ElectiveSub::getId).distinct().collect(Collectors.toList());
            LambdaQueryWrapper<Score> scoreLambdaQueryWrapper = new LambdaQueryWrapper<Score>();
            scoreLambdaQueryWrapper.eq(Score::getStuId, student.getId());
            scoreLambdaQueryWrapper.in(Score::getElectiveId, electiveSubIdList);
            List<Score> scoreList = scoreMapper.selectList(scoreLambdaQueryWrapper);
            for (ElectiveSub electiveSub: electiveSubList) {
                if (electiveSub.getSubId() == -1) {
                    if (optionMap.get(electiveSub.getId()) != null) {
                        if (optionMap.get(electiveSub.getId()) != null) {
                            //学生选科id
                            electiveSub.setSubId(optionMap.get(electiveSub.getId()).getSubId());
                        }

                    }else {
                        //表示未选
                        continue;
                    }
                }
                if (electiveSub.getSubId() != -1 && subjectMap.get(electiveSub.getSubId()) != null) {
                    //科目名
                    String subName = subjectMap.get(electiveSub.getSubId()).getName();
                    //获取大项,并过滤性别
                    List<SubItem> subItems = subItemListMap.get(electiveSub.getSubId()).stream().filter(e -> e.getItemNo().equals(0) && (e.getSextype().equals(0) || e.getSextype().equals(student.getSex()))).collect(Collectors.toList());
                    FinalScore finalScore = new FinalScore();
                    finalScore.setScoreList(scoreList.stream().filter(new Predicate<Score>() {
                        @Override
                        public boolean test(Score score) {
                            return score.getItemNo().equals(0) && score.getElectiveId().equals(electiveSub.getId());
                        }
                    }).collect(Collectors.toList()));

                    if(subItems.size()>0){
                        //50米跑/15米X4往返跑
                        if("50米跑".equals(subName)||"15米x4往返跑".equals(subName)){
                            res.setScore50(finalScore.getConversionScore());
                            res.setScore50_raw(finalScore.getRawScore());
                            if(Objects.nonNull(finalScore.getConversionScore())){
                                total = total.add(finalScore.getConversionScore());
                            }
                        }     //1分钟跳绳
                        else if("1分钟跳绳".equals(subName)){
                            res.setScoreRopeSkipping(finalScore.getConversionScore());
                            res.setScoreRopeSkipping_raw(finalScore.getRawScore());
                            if(Objects.nonNull(finalScore.getConversionScore())){
                                total = total.add(finalScore.getConversionScore());
                            }
                        }
                        else if("1000米跑/800米跑".equals(subName)){
                            res.setScore800Or1000(finalScore.getConversionScore());
                            res.setScore800Or1000_raw(finalScore.getRawScore());
                            if(Objects.nonNull(finalScore.getConversionScore())){
                                total = total.add(finalScore.getConversionScore());
                            }
                        }
                        else {
                            if(req.getType() ==  null){
                                if(electiveSub.getType()!=null&&(electiveSub.getType()==2 || electiveSub.getType()==3)){
                                    if(res.getOption1Name()==null){
                                        res.setOption1Name(SubjectEnum.getEnumBySubId(electiveSub.getSubId()).getMessage());
                                        res.setScoreOption1(finalScore.getConversionScore());
                                        res.setScoreOption1_raw(finalScore.getRawScore());
                                        if(Objects.nonNull(finalScore.getConversionScore())){
                                            total = total.add(finalScore.getConversionScore());
                                        }
                                    }
                                    else {
                                        res.setOption2Name(subName);
                                        res.setScoreOption2(finalScore.getConversionScore());
                                        res.setScoreOption2_raw(finalScore.getRawScore());
                                        if(Objects.nonNull(finalScore.getConversionScore())){
                                            total = total.add(finalScore.getConversionScore());
                                        }
                                    }
                                }
                            }
                            else if(req.getType() ==  1){
                                if(electiveSub.getType()!=null&&(electiveSub.getType()==2)){
                                    if(res.getOption1Name()==null){
                                        res.setOption1Name(subName);
                                        res.setScoreOption1(finalScore.getConversionScore());
                                        res.setScoreOption1_raw(finalScore.getRawScore());
                                        if(Objects.nonNull(finalScore.getConversionScore())){
                                            total = total.add(finalScore.getConversionScore());
                                        }
                                    }
                                    else {
                                        res.setOption2Name(subName);
                                        res.setScoreOption2(finalScore.getConversionScore());
                                        res.setScoreOption2_raw(finalScore.getRawScore());
                                        if(Objects.nonNull(finalScore.getConversionScore())){
                                            total = total.add(finalScore.getConversionScore());
                                        }
                                    }
                                }
                            }
                            else if(req.getType() ==  2){
                                if(electiveSub.getType()!=null&&(electiveSub.getType()==3)){
                                    if(res.getOption1Name()==null){
                                        res.setOption1Name(subName);
                                        res.setScoreOption1(finalScore.getConversionScore());
                                        res.setScoreOption1_raw(finalScore.getRawScore());
                                        if(Objects.nonNull(finalScore.getConversionScore())){
                                            total = total.add(finalScore.getConversionScore());
                                        }
                                    }
                                    else {
                                        res.setOption2Name(subName);
                                        res.setScoreOption2(finalScore.getConversionScore());
                                        res.setScoreOption2_raw(finalScore.getRawScore());
                                        if(Objects.nonNull(finalScore.getConversionScore())){
                                            total = total.add(finalScore.getConversionScore());
                                        }
                                    }
                                }
                            }

                        }

                    }

                }
            }
            res.setTotal(total);
            studentRes.add(res);
        }
        String schoolName = schoolMapper.getSchoolNameById(userBO.getSchoolId());
        try {
            // 设置输出的格式
            response.setContentType("application/octet-stream");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Access-Control-Expose-Headers","Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("fileName","utf-8"));
            ScoreWordUtil.getScoreTable(response.getOutputStream(),studentRes,schoolName,req);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public TransScoreRes getScore(ElectiveSub sub,List<Score> scoreList) {
        //查询科目为大项还是小项
        LambdaQueryWrapper<SubItem>lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SubItem::getSubId,sub.getSubId());
        List<SubItem> subItems = subItemMapper.selectList(lambdaQueryWrapper);
        if (subItems.size()>1) {
            TransScoreRes transScore = new TransScoreRes();
            List<TransScoreRes.TransScoreItem> transScoreItemList = new ArrayList<>();
            Map<Integer, List<Score>> map = scoreList.stream().collect(Collectors.groupingBy(Score::getItemNo));
            map.forEach((key, value) -> {
                AtomicReference<String> highest = new AtomicReference<String>("");
                AtomicReference<Double> highestConv = new AtomicReference<>(0.0);
                List<Score> scoreList2 = value;
                AtomicBoolean isTrue = new AtomicBoolean(true);
                scoreList2.stream().max(Comparator.comparingDouble(e -> {
                    if (e.getConversionScore() != null) {
                        return e.getConversionScore().doubleValue();
                    }
                    return 0;
                })).ifPresent(e -> {
                    if (e.getItemNo() != null && e.getItemNo() != 0 && e.getItemNo() != -0) {
                        highest.set(e.getRawScore());
                        if (e.getConversionScore() != null) {
                            highestConv.set(e.getConversionScore().doubleValue());
                        }
                    } else {
                        isTrue.set(false);
                    }

                });
                if (isTrue.get()) {
                    TransScoreRes.TransScoreItem transScoreItem = new TransScoreRes.TransScoreItem();
                    transScoreItem.setRawScore(highest.get());
                    transScoreItem.setConvScore(String.valueOf(highestConv.get()));
                    transScoreItemList.add(transScoreItem);
                }

            });
            double totalScore = 0;
            for (int i = 0; i < transScoreItemList.size(); i++) {
                totalScore += Double.parseDouble(transScoreItemList.get(i).getConvScore());
            }
            transScore.setConvScore(String.valueOf(totalScore));
            transScore.setTransScoreItemList(transScoreItemList);
            return transScore;
        } else {
            TransScoreRes transScore = new TransScoreRes();

            AtomicReference<String> highest = new AtomicReference<String>("");
            AtomicReference<Double> highestConv = new AtomicReference<>(0.0);
            scoreList.stream().max(Comparator.comparingDouble(e -> {
                if (e.getConversionScore() != null) {
                    return e.getConversionScore().doubleValue();
                }
                return 0;
            })).ifPresent(e -> {
                highest.set(e.getRawScore());
                ;
                if (e.getConversionScore() != null) {
                    highestConv.set(e.getConversionScore().doubleValue());
                }
            });

            transScore.setRawScore(highest.get());
            transScore.setConvScore(String.valueOf(highestConv.get()));
            return transScore;
        }
    }

}
